﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms.Layout;

namespace client
{
    public class LedStackPanel : Panel
    {
        private bool scrollable = true;
        private bool scrollbarsVisible = false;
        private LedStackEngine layoutEngine = null;
        private Orientation orientation = Orientation.Vertical;

        public LedStackPanel()
        {
            AutoScroll = true;
        }

        public override LayoutEngine LayoutEngine
        {
            get
            {
                if (layoutEngine == null)
                    layoutEngine = new LedStackEngine();
                return layoutEngine;
            }
        }

        [Browsable(true)]
        public bool Scrollable
        {
            get { return scrollable; }
            set { scrollable = value; AutoScroll = scrollable; PerformLayout(); }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override bool AutoScroll
        {
            get { return base.AutoScroll; }
            set { base.AutoScroll = Scrollable ? value : false; }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override bool AutoSize
        {
            get { return false; }
            set { }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override Point AutoScrollOffset
        {
            get { return base.AutoScrollOffset; }
            set { base.AutoScrollOffset = value; }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override AutoSizeMode AutoSizeMode
        {
            get { return base.AutoSizeMode; }
            set { }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Size AutoScrollMargin
        {
            get { return base.AutoScrollMargin; }
            set { base.AutoScrollMargin = value; }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Size AutoScrollMinSize
        {
            get { return base.AutoScrollMinSize; }
            set { base.AutoScrollMinSize = value; }
        }

        [Browsable(true), DefaultValue(Orientation.Vertical)]
        public Orientation LayoutOrientation
        {
            get { return orientation; }
            set { orientation = value; PerformLayout(); }
        }

        private class LedStackEngine : LayoutEngine
        {
            public override bool Layout(object container, LayoutEventArgs layoutEventArgs)
            {
                LedStackPanel parent = container as LedStackPanel;

                Rectangle position = new Rectangle(
                    parent.Margin.Left + parent.Padding.Left + parent.ClientRectangle.Left + parent.DisplayRectangle.Left,
                    parent.Margin.Top + parent.Padding.Top + parent.ClientRectangle.Top + parent.DisplayRectangle.Top, 0, 0);

                parent.Focus();

                int heightNeeded = parent.Height;
                int widthNeeded = parent.Width;

                // Create a list of control rectangles. These will speed up the layout process
                Rectangle[] layout = new Rectangle[parent.Controls.Count];
                for (int c = 0; c < parent.Controls.Count; c++)
                {
                    if (!parent.Controls[c].Visible)
                        continue;

                    switch (parent.orientation)
                    {
                        case Orientation.Vertical:
                            layout[c] = new Rectangle(position.Location, new Size(parent.ClientRectangle.Width - parent.Padding.Horizontal - parent.Margin.Horizontal, parent.Controls[c].Height));
                            position.Offset(0, layout[c].Height + parent.Margin.Bottom);
                            heightNeeded = layout[c].Bottom + parent.Margin.Bottom + parent.Padding.Bottom;
                            break;

                        case Orientation.Horizontal:
                            layout[c] = new Rectangle(position.Location, new Size(parent.Controls[c].Width, parent.ClientRectangle.Height - parent.Padding.Vertical - parent.Margin.Vertical));
                            position.Offset(layout[c].Width + parent.Margin.Right, 0);
                            widthNeeded = layout[c].Right + parent.Margin.Right + parent.Padding.Right;
                            break;
                    }
                }


                // Scrollbars are needed?
                if (layout.Length > 0 && parent.scrollable &&
                    ((heightNeeded > parent.ClientRectangle.Height || parent.DisplayRectangle.Top < 0) && parent.orientation == Orientation.Vertical ||
                    (widthNeeded > parent.ClientRectangle.Width || parent.DisplayRectangle.Left < 0) && parent.orientation == Orientation.Horizontal))
                {
                    if (!parent.scrollbarsVisible)
                    {
                        // Scrollbars will be visible
                        // Redo the layout stripping the size of the scrollbars
                        for (int r = 0; r < layout.Length; r++)
                        {
                            switch (parent.orientation)
                            {
                                case Orientation.Vertical:
                                    layout[r].Width -= SystemInformation.VerticalScrollBarWidth;
                                    break;

                                case Orientation.Horizontal:
                                    layout[r].Height -= SystemInformation.HorizontalScrollBarHeight;
                                    break;
                            }
                        }

                        // Activate scrollbars
                        parent.scrollbarsVisible = true;
                    }
                }
                else if (parent.scrollable)
                {
                    if (parent.scrollbarsVisible)
                    {
                        // Scrollbars is no longer needed
                        // Redo the layout and add the size of the scrollbars
                        for (int r = 0; r < layout.Length; r++)
                        {
                            switch (parent.orientation)
                            {
                                case Orientation.Vertical:
                                    layout[r].Width += SystemInformation.VerticalScrollBarWidth;
                                    break;

                                case Orientation.Horizontal:
                                    layout[r].Height += SystemInformation.HorizontalScrollBarHeight;
                                    break;
                            }
                        }

                        // Deativate scrollbars
                        parent.scrollbarsVisible = false;
                    }
                }
                else
                {
                    if (parent.orientation == Orientation.Vertical)
                        parent.Height = heightNeeded;
                    if (parent.orientation == Orientation.Horizontal)
                        parent.Width = widthNeeded;
                }

                // Activate the layout
                for (int c = 0; c < parent.Controls.Count; c++)
                {
                    if (!parent.Controls[c].Visible)
                        continue;

                    parent.Controls[c].SuspendLayout();
                    parent.Controls[c].Left = layout[c].Left;
                    parent.Controls[c].Top = layout[c].Top;
                    parent.Controls[c].Width = layout[c].Width;
                    parent.Controls[c].Height = layout[c].Height;
                    parent.Controls[c].ResumeLayout();
                }

                return false;
            }
        }
    }
}
